package com.ygqh.baby.service.impl;

import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.JsonResult;
import com.foxinmy.weixin4j.mp.api.TmplApi;
import com.foxinmy.weixin4j.mp.message.TemplateMessage;
import com.foxinmy.weixin4j.mp.model.TemplateMessageInfo;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.util.NameValue;
import com.foxinmy.weixin4j.util.StringUtil;
import com.ygqh.baby.ao.Message;
import com.ygqh.baby.ao.WxMessageType;
import com.ygqh.baby.constant.Constant;
import com.ygqh.baby.po.WxAttention;
import com.ygqh.baby.po.YgUser;
import com.ygqh.baby.redis.RedisDao;
import com.ygqh.baby.service.*;
import com.ygqh.baby.service.wechat.api.YgTmplApi;
import com.ygqh.baby.service.wechat.message.YgSubscribeTempMsg;
import com.ygqh.baby.service.wechat.message.YgTemplateMessage;
import com.ygqh.baby.service.wechat.model.SmallTemplateMsg;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.crazycake.shiro.SerializeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

@Service
public class BaseWxMpMessageService extends AbstractService {
    private final Logger logger = Logger.getLogger(BaseWxMpMessageService.class);
    @Autowired
    protected WxMpAuthorityService wxMpAuthorityService;
    @Autowired
    protected YgUserService ygUserService;
    @Autowired
    protected WxSmallAuthorityService wxSmallAuthorityService;
    @Autowired
    protected WxAttentionService wxAttentionService;
    @Autowired
    protected RedisDao redisDao;
    @Value("${micro.msg.appId}")
    protected String appId;
    @Value("${small.appId}")
    protected String smallAppId;

    protected Boolean canSend(YgUser user) {

        if (user == null || StringUtil.isBlank(user.getOpenId()) || !user.getIsSubscribe()) {
            return false;
        }
        return true;
    }

    protected Boolean canSend(Long userId) {

        YgUser user = ygUserService.findById(userId);

        return this.canSend(user);
    }

    protected Boolean canSend(String openId) {

        YgUser user = ygUserService.findByOpenId(openId);

        return this.canSend(user);
    }

    public Message sendTemplateMessage(TemplateMessage tplMessage) {
        TmplApi tmplApi = new TmplApi(wxMpAuthorityService.findTokenHolder());
        JsonResult sendResult = null;
        try {
            sendResult = tmplApi.sendTmplMessage(tplMessage);
        } catch (WeixinException e) {
            /*logger.error("发送微信模板消息失败；openId=【" + tplMessage.getToUser() + "】【" + tplMessage.getHead() + "】" + e.getMessage());
             */
            e.printStackTrace();
            return Message.error(e.getMessage(), null);
        }
        return Message.success(sendResult.getText(), null);
    }

    public String getWxMsgTempId(WxMessageType messageType) {

        String tempId = null;
        if (messageType.getCode() == 0) {
            tempId = this.getMsgTempId(messageType);
        } else if (messageType.getCode() == 10) {
            tempId = this.getSmallMsgTempId(messageType);
        } else if (messageType.getCode() == 20) {
            tempId = this.getSmallMsgTempId(messageType, Constant.YIJIADIAN_PLATFORM_NO);
        }
        return tempId;
    }

    public String getSmallMsgTempId(WxMessageType messageType) {
        return getSmallMsgTempId(messageType, null);
    }

    public String getSmallMsgTempId(WxMessageType messageType, String platformNo) {
        String key;
        if (StringUtils.isBlank(platformNo) || Constant.YIIGOO_PLATFORM_NO.equals(platformNo)) {
            key = String.format("wx_tempid_%s", smallAppId + "_" + messageType.name());
        } else {
            key = String.format("wx_tempid_%s", platformNo + "_small_" + messageType.name());
        }
        String msgTmpId = (String) SerializeUtils.deserialize(redisDao.get(key.getBytes()));
        if (StringUtil.isEmpty(msgTmpId)) {
            List<SmallTemplateMsg> list = getSmallMsgList(platformNo);
            for (SmallTemplateMsg msg : list) {
                if (messageType.getTitle().equals(msg.getTitle())) {
                    redisDao.set(key.getBytes(), SerializeUtils.serialize(msg.getTemplate_id()));
                    return msg.getTemplate_id();
                }
            }
        }
        return msgTmpId;
    }

    public List<SmallTemplateMsg> getSmallMsgList() {
        List<SmallTemplateMsg> allTemplates = null;
        YgTmplApi api = new YgTmplApi(wxSmallAuthorityService.findTokenHolder());
        allTemplates = api.getSmallAllTmplMsg();
        return allTemplates;
    }

    public List<SmallTemplateMsg> getSmallMsgList(String platformNo) {
        YgTmplApi api = new YgTmplApi(wxSmallAuthorityService.findTokenHolder(platformNo));
        return api.getSmallAllTmplMsg();
    }

    private String getMsgTempId(WxMessageType messageType) {

        String key = String.format("wx_tempid_%s", appId + "_" + messageType.name());
        String msgTmpId = (String) SerializeUtils.deserialize(redisDao.get(key.getBytes()));
        if (StringUtil.isEmpty(msgTmpId)) {
            List<TemplateMessageInfo> list = getTemplateMessageList();
            for (TemplateMessageInfo msg : list) {
                if (messageType.getTitle().equals(msg.getTitle())) {
                    redisDao.set(key.getBytes(), SerializeUtils.serialize(msg.getTemplateId()));
                    return msg.getTemplateId();
                }
            }
        }
        return msgTmpId;
    }

    /**
     * 获取模板消息列表
     *
     * @return List<TemplateMessageInfo> 返回类型
     * @throws
     * @Title: getTemplateMessageList
     * @author （guohao）
     * @date 2017年8月3日 下午7:09:33
     * @version V1.0
     */
    public List<TemplateMessageInfo> getTemplateMessageList() {
        List<TemplateMessageInfo> allTemplates = null;
        try {
            TmplApi tmplApi = new TmplApi(wxMpAuthorityService.findTokenHolder());
            allTemplates = tmplApi.getAllTemplates();
        } catch (WeixinException e) {
            allTemplates = new ArrayList<TemplateMessageInfo>();
            e.printStackTrace();
        }
        return allTemplates;
    }

    /**
     * 发送模板消息 可设置字体颜色
     *
     * @param messageType
     * @param openId
     * @param url
     * @param contentMap  map的key 微消息模板的key ; </br> NameValue(color,text) color 为空时
     *                    默认颜色为 #323232
     * @return Message 返回类型
     * @throws
     * @Title: sendTemplateMessage
     * @author （guohao）
     * @date 2017年8月3日 下午7:06:21
     * @version V1.0
     */
    public Message sendTemplateMessage(WxMessageType messageType, String openId, String url, Map<String, NameValue> contentMap) {
        String wxMsgTempId = this.getWxMsgTempId(messageType);
        TemplateMessage tplMessage = new TemplateMessage(openId, wxMsgTempId, "", url);
        for (Entry<String, NameValue> entry : contentMap.entrySet()) {
            String color = StringUtil.isBlank(entry.getValue().getName()) ? "#323232" : entry.getValue().getName();
            if (entry.getKey().equals("first")) {
                tplMessage.pushHead(color, entry.getValue().getValue());
            }
            tplMessage.pushItem(entry.getKey(), color, entry.getValue().getValue());
        }

        return this.sendTemplateMessage(tplMessage);
    }

    public Message sendTemplateMessage(WxMessageType messageType, YgUser user, String url, Map<String, NameValue> contentMap) {
        if (!canSend(user)) {
            return Message.error("该用户未绑定微信，或已取关", user.getId());
        }

        return this.sendTemplateMessage(messageType, user.getOpenId(), url, contentMap);
    }

    /**
     * 只适用于模板的key 为keyword1 等等
     *
     * @param messageType
     * @param head
     * @param openId
     * @param url
     * @param keyword     这里需按照keyword顺序依次传参
     * @return Message 返回类型
     * @throws
     * @Title: sendTemplateMessage
     * @author （guohao）
     * @date 2017年8月3日 下午7:01:41
     * @version V1.0
     */
    public Message sendTemplateMessage(WxMessageType messageType, String head, String remark, String openId, String url, String... keyword) {

        Message message = null;
        try {
            String wxMsgTempId = this.getWxMsgTempId(messageType);
            TemplateMessage tplMessage = null;
            if (messageType.getCode() == 0) {
                tplMessage = new TemplateMessage(openId, wxMsgTempId, head, url);
            } else if (messageType.getCode() == 10 || messageType.getCode() == 20) {
                WxAttention attention = wxAttentionService.findByOpenId(openId);
                if (attention == null) {
                    message = Message.error("发送[" + messageType.getTitle() + "] 给[" + openId + "]无有效formId", openId);
                } else {
                    tplMessage = new YgTemplateMessage(openId, wxMsgTempId, head, url, attention.getEvent());
                    ((YgTemplateMessage) tplMessage).setPlatformNo(getPlatformNo(messageType));
                    wxAttentionService.updateUpdateTime(attention.getId());
                }
            } else {
                message = Message.error("未知的模板消息", messageType);
            }
            if (tplMessage != null) {
                tplMessage.pushHead("#323232", head);
                tplMessage.pushTail(remark);
                for (int i = 0; i < keyword.length; i++) {
                    tplMessage.pushItem("keyword" + (i + 1), "#323232", keyword[i]);
                }
                message = this.sendTemplateMessage(tplMessage);
            }

        } catch (Exception e) {
            e.printStackTrace();
            message = Message.error("发送消息失败。", e.getMessage());
        }
        return message;

    }

    public Message sendTempMessage(WxMessageType messageType, String openId, String url, String... keyword) {
        return sendTemplateMessage(messageType, null, null, openId, url, keyword);
    }

    String getPlatformNo(WxMessageType messageType) {
        if (messageType.getCode().equals(0) || messageType.getCode().equals(10)) {
            return Constant.YIIGOO_PLATFORM_NO;
        } else if (messageType.getCode().equals(20)) {
            return Constant.YIJIADIAN_PLATFORM_NO;
        }
        return null;
    }

    public Message sendTemplateMessage(WxMessageType messageType, String head, String remark, YgUser user, String url, String... keyword) {
        if (!canSend(user)) {
            return Message.error("该用户未绑定微信，或已取关", user.getId());
        }
        return this.sendTemplateMessage(messageType, head, remark, user.getOpenId(), url, keyword);
    }

    /**
     * 发送一次性订阅消息
     *
     * @param subscribeTempMsg
     * @return Message 返回类型
     * @throws
     * @Title: sendSubscribeMsg
     * @author （guohao）
     * @date 2017年8月8日 下午12:03:10
     * @version V1.0
     */
    public Message sendSubscribeMsg(YgSubscribeTempMsg subscribeTempMsg) {
        TokenHolder tokenHolder = wxMpAuthorityService.findTokenHolder();
        YgTmplApi tmplApi = new YgTmplApi(tokenHolder);
        try {
            JsonResult result = tmplApi.sendTmplMessage(subscribeTempMsg);
            return Message.success(result.getDesc(), null);
        } catch (WeixinException e) {
            e.printStackTrace();
            return Message.error(e.getMessage(), null);
        }
    }

    /**
     * 发送一次性订阅消息
     *
     * @param openId
     * @param title      标题
     * @param templateId
     * @param url        跳转页面
     * @param scene      场景值
     * @param content    消息内容
     * @return Message 返回类型
     * @throws
     * @Title: sendSubscribeMsg
     * @author （guohao）
     * @date 2017年8月8日 下午12:04:22
     * @version V1.0
     */
    public Message sendSubscribeMsg(String openId, String title, String templateId, String url, String scene, String content) {
        YgSubscribeTempMsg tmpMsg = new YgSubscribeTempMsg(openId, templateId, title, url, scene);

        tmpMsg.pushItem("content", "#323232", content);
        return this.sendSubscribeMsg(tmpMsg);
    }
}
